package com.wonders.hisdoctor.station.project.examine.service.impl;

import com.wonders.his.common.exception.CustomException;
import com.wonders.his.common.utils.StringUtils;
import com.wonders.his.common.utils.validator.ValidateUtils;
import com.wonders.his.common.utils.validator.group.InsertGroup;
import com.wonders.his.framework.utils.oracle.IdUtils;
import com.wonders.hisdoctor.station.constant.Constants;
import com.wonders.hisdoctor.station.constant.ServiceConstant;
import com.wonders.hisdoctor.station.enums.ChargeIndicatorEnum;
import com.wonders.hisdoctor.station.enums.ItemClassEnum;
import com.wonders.hisdoctor.station.enums.OracleSequenceEnum;
import com.wonders.hisdoctor.station.enums.ResultStatusEnum;
import com.wonders.hisdoctor.station.project.base.domain.*;
import com.wonders.hisdoctor.station.project.base.mapper.*;
import com.wonders.hisdoctor.station.project.examine.mapper.ExamineMapper;
import com.wonders.hisdoctor.station.project.examine.service.IExamineService;
import com.wonders.hisdoctor.station.project.examine.vo.*;
import com.wonders.hisdoctor.station.util.CommonUtil;
import com.wonders.hisdoctor.station.util.PrecsIdGenerator;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 检查申请service实现
 *
 * @author zhanghaonan
 * <p>
 * Create: 2021-02-04
 */
@Service
public class ExamineServiceImpl implements IExamineService {

    @Autowired
    private ExamineMapper examineMapper;

    @Autowired
    private ExamMasterMapper examMasterMapper;

    @Autowired
    private ExamAppointsMapper examAppointsMapper;

    @Autowired
    private ExamItemsMapper examItemsMapper;

    @Autowired
    private OutpOrdersMapper outpOrdersMapper;

    @Autowired
    private OutpOrdersTMapper outpOrdersTMapper;

    @Autowired
    private OutpTreatRecMapper outpTreatRecMapper;

    @Autowired
    private OutpTreatRecTMapper outpTreatRecTMapper;

    @Autowired
    private IdUtils idUtils;

    @Autowired
    private PrecsIdGenerator precsIdGenerator;

    @Autowired
    private CommonUtil commonUtil;

    @Override
    public List<ExamineMenuVo> selectCheckMenu(String hospitalCode) {
        return examineMapper.selectCheckMenu(hospitalCode);
    }

    @Override
    public List<ExamItemsVo> selectItemList(ExamItemsRequestVo vo) {
        return examineMapper.selectItemList(vo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int save(ExamineSaveVo vo) {
        if (CollectionUtils.isEmpty(vo.getOutpTreatRecList())) {
            throw new CustomException("请选择检查申请项目");
        }
        //处方主键序号
        String serialNo = idUtils.getNextVal(OracleSequenceEnum.SEQ_OUTP_ORDERS.getCode()).toString();

        //处方主记录OUTP_ORDERS
        OutpOrders outpOrders = vo.getOutpOrders();
        ValidateUtils.validateEntity(outpOrders, new Class[]{InsertGroup.class});
        outpOrders.setSerialNo(serialNo);
        outpOrdersMapper.insert(outpOrders);
        //门诊医嘱处方主记录临时表OUTP_ORDERS_T
        OutpOrdersT outpOrdersT = new OutpOrdersT();
        BeanUtils.copyProperties(outpOrders, outpOrdersT);
        outpOrdersTMapper.add(outpOrdersT);

        List<OutpTreatRec> outpTreatRecList = new ArrayList<>();
        List<OutpTreatRecT> outpTreatRecTList = new ArrayList<>();
        List<ExamItems> examItemsList = new ArrayList<>();
        //项目序号
        int itemNo = 0;
        for (int i = 0; i < vo.getOutpTreatRecList().size(); i++) {
            OutpTreatRec otr = vo.getOutpTreatRecList().get(i);
            if (!StringUtils.isEmpty(otr.getSerialNo())) {
                continue;
            }
            itemNo = itemNo + 1;
            //申请单序号
            String prescId = precsIdGenerator.getPrescId();
            //检查主记录EXAM_MASTER
            ExamMaster examMaster = new ExamMaster();
            BeanUtils.copyProperties(vo.getExamMaster(), examMaster);
            BeanUtils.copyProperties(otr, examMaster);
            examMaster.setExamNo(prescId);
            examMaster.setResultStatus(ResultStatusEnum.APPLICATION_RECEIPT.getCode());//保存时，RESULT_STATUS默认存１
            examMaster.setChargeIndicator(ChargeIndicatorEnum.ORDERED.getCode());//收费标记：0-已开单，1-已缴费，2-已退费
            examMaster.setPatientId(vo.getOutpOrders().getPatientId());
            examMaster.setVisitDate(vo.getOutpOrders().getVisitDate());
            examMaster.setVisitNo(vo.getOutpOrders().getVisitNo());
            examMaster.setReqDept(vo.getOutpOrders().getOrderedBy());//申请科室
            examMaster.setReqPhysician(vo.getOutpOrders().getDoctor());//申请医生
            //todo 改为获取数据库当前时间
            examMaster.setReqDateTime(new Date());//申请时间
            ValidateUtils.validateEntity(examMaster, new Class[]{InsertGroup.class});
            examMasterMapper.insert(examMaster);
            //检查预约记录EXAM_APPOINTS
            ExamAppoints examAppoints = new ExamAppoints();
            BeanUtils.copyProperties(examMaster, examAppoints);
            examAppointsMapper.insert(examAppoints);
            //检查项目记录EXAM_ITEMS
            ExamItems examItems = new ExamItems();
            BeanUtils.copyProperties(otr, examItems);
            examItems.setExamNo(prescId);
            examItems.setExamItemNo(Constants.ITEM_NO);
            examItems.setExamItemCode(otr.getItemCode());
            examItems.setExamItem(otr.getItemName());
            examItemsList.add(examItems);

            //检查治疗医嘱明细记录OUTP_TREAT_REC
            OutpTreatRec outpTreatRec = new OutpTreatRec();
            BeanUtils.copyProperties(otr, outpTreatRec);
            outpTreatRec.setSerialNo(serialNo);
            outpTreatRec.setItemNo(itemNo);
            outpTreatRec.setItemClass(ItemClassEnum.EXAM.getCode());
            outpTreatRec.setChargeIndicator(ChargeIndicatorEnum.ORDERED.getCode());//收费标记：0-已开单，1-已缴费，2-已退费
            outpTreatRec.setAppointNo(prescId);
            outpTreatRec.setAppointItemNo(Constants.ITEM_NO);
            outpTreatRecList.add(outpTreatRec);

            //检查治疗医嘱明细临时表OUTP_TREAT_REC_T
            OutpTreatRecT outpTreatRecT = new OutpTreatRecT();
            BeanUtils.copyProperties(outpTreatRec, outpTreatRecT);
            outpTreatRecTList.add(outpTreatRecT);
        }
        if (!CollectionUtils.isEmpty(outpTreatRecList)) {
            outpTreatRecMapper.insertBatch(outpTreatRecList);
            outpTreatRecTMapper.insertBatch(outpTreatRecTList);
            examItemsMapper.insertBatch(examItemsList);
        }
        return 1;
    }

    @Override
    public List<OutpTreatRecVo> selectOutpTreatRec(ExamineRequestVo vo) {
        return examineMapper.selectOutpTreatRec(vo);
    }

    /** 当前申请项目 */
    private static final String CURRENT_ITEM = "当前申请项目“";

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteOutpTreatRec(List<OutpTreatRec> list) {
        //剔除未入库的
        list = list.stream().filter(c -> StringUtils.isNotEmpty(c.getSerialNo())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(list)) {
            return 1;
        }
        for (OutpTreatRec outpTreatRec : list) {
            OutpTreatRec result = outpTreatRecMapper.selectById(outpTreatRec);
            if (result != null) {
                if (!ItemClassEnum.EXAM.getCode().equals(result.getItemClass())) {
                    throw new CustomException(CURRENT_ITEM + result.getItemName() + "”不是检查项目");
                }
                if (ChargeIndicatorEnum.PAID.getCode() == result.getChargeIndicator()) {
                    throw new CustomException(CURRENT_ITEM + result.getItemName() + "”已缴费，不能删除");
                }
                if (ChargeIndicatorEnum.RETURN_PAID.getCode() == result.getChargeIndicator()) {
                    throw new CustomException(CURRENT_ITEM + result.getItemName() + "”已退费，不能删除");
                }
            } else {
                throw new CustomException("当前申请项目不存在");
            }
        }
        //删除检查医嘱明细表
        int count = examineMapper.deleteOutpTreatRec(list);
        if (count < list.size()) {
            throw new CustomException("删除失败");
        }
        //删除明细临时表
        examineMapper.deleteOutpTreatRecT(list);
        //删除检查主记录、检查预约记录、检查项目记录
        examineMapper.deleteExamItems(list);
        //判断明细表为空后，删除主记录
        list.forEach(outpTreatRec -> {
            Map<String, Object> hashMap = new HashMap<>();
            hashMap.put(ServiceConstant.SERIAL_NO, outpTreatRec.getSerialNo());
            hashMap.put(ServiceConstant.ITEM_CLASS, ItemClassEnum.EXAM.getCode());
            List<OutpTreatRec> outpTreatRecs = outpTreatRecMapper.selectByMap(hashMap);
            if (CollectionUtils.isEmpty(outpTreatRecs)) {
                outpOrdersMapper.deleteById(outpTreatRec.getSerialNo());
                outpOrdersTMapper.deleteById(outpTreatRec.getSerialNo());
            }
        });
        return count;
    }

    @Override
    public List<OutpTreatRecVo> selectExamineHistory(ExamineHistoryRequestVo vo) {
        return examineMapper.selectExamineHistory(vo);
    }

    @Override
    public List<PrintExamineVo> selectPrintExamine(List<OutpTreatRecVo> list) {
        List<PrintExamineVo> printExamineVos = examineMapper.selectPrintExamine(list);
        for (PrintExamineVo vo : printExamineVos) {
            vo.setPrintTitle(commonUtil.setPrintTitle(vo.getHospitalCode()));
        }
        return printExamineVos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<PrintExamineVo> saveAndPrint(ExamineSaveVo vo) {
        if (CollectionUtils.isEmpty(vo.getOutpTreatRecList())) {
            throw new CustomException("请选择检查申请项目");
        }
        //处方主键序号
        String serialNo = idUtils.getNextVal(OracleSequenceEnum.SEQ_OUTP_ORDERS.getCode()).toString();

        //处方主记录OUTP_ORDERS
        OutpOrders outpOrders = vo.getOutpOrders();
        ValidateUtils.validateEntity(outpOrders, new Class[]{InsertGroup.class});
        outpOrders.setSerialNo(serialNo);
        outpOrdersMapper.insert(outpOrders);
        //门诊医嘱处方主记录临时表OUTP_ORDERS_T
        OutpOrdersT outpOrdersT = new OutpOrdersT();
        BeanUtils.copyProperties(outpOrders, outpOrdersT);
        outpOrdersTMapper.add(outpOrdersT);

        List<OutpTreatRec> outpTreatRecList = new ArrayList<>();
        List<OutpTreatRecT> outpTreatRecTList = new ArrayList<>();
        List<ExamItems> examItemsList = new ArrayList<>();
        //打印传参list
        List<OutpTreatRecVo> outpTreatRecPrintList = new ArrayList<>();
        //项目序号
        int itemNo = 0;
        for (int i = 0; i < vo.getOutpTreatRecList().size(); i++) {
            OutpTreatRec otr = vo.getOutpTreatRecList().get(i);
            if (!StringUtils.isEmpty(otr.getSerialNo())) {
                continue;
            }
            itemNo = itemNo + 1;
            //申请单序号
            String prescId = precsIdGenerator.getPrescId();
            //检查主记录EXAM_MASTER
            ExamMaster examMaster = new ExamMaster();
            BeanUtils.copyProperties(vo.getExamMaster(), examMaster);
            BeanUtils.copyProperties(otr, examMaster);
            examMaster.setExamNo(prescId);
            examMaster.setResultStatus(ResultStatusEnum.APPLICATION_RECEIPT.getCode());//保存时，RESULT_STATUS默认存１
            examMaster.setChargeIndicator(ChargeIndicatorEnum.ORDERED.getCode());//收费标记：0-已开单，1-已缴费，2-已退费
            examMaster.setPatientId(vo.getOutpOrders().getPatientId());
            examMaster.setVisitDate(vo.getOutpOrders().getVisitDate());
            examMaster.setVisitNo(vo.getOutpOrders().getVisitNo());
            examMaster.setReqDept(vo.getOutpOrders().getOrderedBy());//申请科室
            examMaster.setReqPhysician(vo.getOutpOrders().getDoctor());//申请医生
            //todo 改为获取数据库当前时间
            examMaster.setReqDateTime(new Date());//申请时间
            ValidateUtils.validateEntity(examMaster, new Class[]{InsertGroup.class});
            examMasterMapper.insert(examMaster);
            //检查预约记录EXAM_APPOINTS
            ExamAppoints examAppoints = new ExamAppoints();
            BeanUtils.copyProperties(examMaster, examAppoints);
            examAppointsMapper.insert(examAppoints);
            //检查项目记录EXAM_ITEMS
            ExamItems examItems = new ExamItems();
            BeanUtils.copyProperties(otr, examItems);
            examItems.setExamNo(prescId);
            examItems.setExamItemNo(Constants.ITEM_NO);
            examItems.setExamItemCode(otr.getItemCode());
            examItems.setExamItem(otr.getItemName());
            examItemsList.add(examItems);

            //检查治疗医嘱明细记录OUTP_TREAT_REC
            OutpTreatRec outpTreatRec = new OutpTreatRec();
            BeanUtils.copyProperties(otr, outpTreatRec);
            outpTreatRec.setSerialNo(serialNo);
            outpTreatRec.setItemNo(itemNo);
            outpTreatRec.setItemClass(ItemClassEnum.EXAM.getCode());
            outpTreatRec.setChargeIndicator(ChargeIndicatorEnum.ORDERED.getCode());//收费标记：0-已开单，1-已缴费，2-已退费
            outpTreatRec.setAppointNo(prescId);
            outpTreatRec.setAppointItemNo(Constants.ITEM_NO);
            outpTreatRec.setVisitDate(vo.getOutpOrders().getVisitDate());
            outpTreatRec.setVisitNo(vo.getOutpOrders().getVisitNo());
            outpTreatRecList.add(outpTreatRec);
            OutpTreatRecVo outpTreatRecVo = new OutpTreatRecVo();
            BeanUtils.copyProperties(outpTreatRec, outpTreatRecVo);
            outpTreatRecPrintList.add(outpTreatRecVo);

            //检查治疗医嘱明细临时表OUTP_TREAT_REC_T
            OutpTreatRecT outpTreatRecT = new OutpTreatRecT();
            BeanUtils.copyProperties(outpTreatRec, outpTreatRecT);
            outpTreatRecTList.add(outpTreatRecT);
        }
        if (!CollectionUtils.isEmpty(outpTreatRecList)) {
            outpTreatRecMapper.insertBatch(outpTreatRecList);
            outpTreatRecTMapper.insertBatch(outpTreatRecTList);
            examItemsMapper.insertBatch(examItemsList);
        }
        //添加上之前已经保存过的，用于打印
        for (int i = 0; i < vo.getOutpTreatRecList().size(); i++) {
            OutpTreatRecVo otr = vo.getOutpTreatRecList().get(i);
            if (!StringUtils.isEmpty(otr.getSerialNo())) {
                outpTreatRecPrintList.add(otr);
            }
        }
        return this.selectPrintExamine(outpTreatRecPrintList);
    }
}
